//
//  ViewController.m
//  MyBluetooth
//
//  Created by s on 14-2-11.
//  Copyright (c) 2014年 sunward. All rights reserved.
//


#import "ViewController.h"

/*
UUID来确定你要干的事情，特征和服务的UUID都是外设定义好的。我们只需要读取，确定你要读取什么的时候，就去判断UUID是否相符。
 一般来说我们使用的iPhone都是做centralManager的，蓝牙模块是peripheral的，所以我们是want datas，需要接受数据。
 1.判断状态为powerOn，然后执行扫描
 2.停止扫描，连接外设
 3.连接成功，寻找服务
 4.在服务里寻找特征
 5.为特征添加通知
 5.通知添加成功，那么就可以实时的读取value[也就是说只要外设发送数据[一般外设的频率为10Hz]，代理就会调用此方法]。
 6.处理接收到的value，[hex值，得转换]
 之后就自由发挥了，在这期间都是通过代理来实现的，也就是说你只需要处理你想要做的事情，代理会帮你调用方法。[别忘了添加代理]
 */

@interface ViewController (){
    NSTimer *scanPerT;
}


@end

@implementation ViewController 

- (void)viewDidLoad
{
    [super viewDidLoad];
	//打印相关调试信息
    [self addLog:@"viewDidLoad"];
    self.cbCentralMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


-(NSMutableArray *)perArr{
    if (!_perArr) {
        _perArr=[[NSMutableArray alloc]init];
    }
    return _perArr;
}

-(NSMutableArray *)perConnectedArr{
    if (!_perConnectedArr) {
        _perConnectedArr=[[NSMutableArray alloc]init];
    }
    return _perConnectedArr;
}

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    //设置导航栏右侧按钮标题,这里获取到蓝牙的状态
    
    //搜索与定时搜索外围设备
    [self scanForPeripherals];
    scanPerT=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(scanForPeripherals) userInfo:nil repeats:YES];
}

//搜索外围设备
-(void)scanForPeripherals{
    //先清空数据
    [self.cbCentralMgr stopScan];
    [self.perArr removeAllObjects];
    [self.perConnectedArr removeAllObjects];
    
    //搜索
    NSDictionary * dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],CBCentralManagerScanOptionAllowDuplicatesKey, nil];
    [self.cbCentralMgr scanForPeripheralsWithServices:nil options:dic];
}


-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    self.cbCentralMgr.delegate = nil;//清空代理人
    [self.cbCentralMgr stopScan];//停止所搜外围设备
    [scanPerT invalidate];
}

#pragma mark - tool
-(void)addLog:(NSString*)log
{
    NSLog(@"%@",log);
}

-(void)addLogWithService:(CBService*)service
{
    [self addLog:[NSString stringWithFormat:@"%@ uuid:%@",service,service.UUID]];
    
}
-(void)addLogWithCharacteristic:(CBCharacteristic*)characteristic
{
    [self addLog:[NSString stringWithFormat:@"%@ characteristic:%@",characteristic,characteristic.UUID]];
    
}


#pragma mark -CBCentralManagerDelegate
-(NSString*)getcentralManagerStateStr:(CBCentralManager*)central
{
    NSString* result;
    switch (central.state) {
        case CBCentralManagerStatePoweredOff:
            result = @"设备关闭";
            break;
            
        case CBCentralManagerStatePoweredOn:
            result = @"设备开启";
            break;
            
        case CBCentralManagerStateResetting:
            result = @"设备重置";
            break;
            
        case CBCentralManagerStateUnauthorized:
            result = @"未授权";
            break;
            
        case CBCentralManagerStateUnknown:
            result = @"未知";
            break;
            
        case CBCentralManagerStateUnsupported:
            result = @"不支持";
            break;
            
        default:
            result = @"没有啦";
            break;
    }
    return result;
}

//更新状态 ，只有状态可用的时候才能够进行创建服务，发布等等操作
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    [self addLog:@"蓝牙设备状态开始更新"];
    switch (central.state) {
        case CBCentralManagerStateUnknown:
            [self addLog:@"未知"];
            break;
            
        case CBCentralManagerStateResetting:
            [self addLog:@"设备重置"];
            break;
            
        case CBCentralManagerStateUnsupported:
            [self addLog:@"不支持"];
            break;
            
        case CBCentralManagerStateUnauthorized:
            [self addLog:@"未授权"];
            break;
            
        case CBCentralManagerStatePoweredOff:
            [self addLog:@"设备关闭"];
            break;
            
        case CBCentralManagerStatePoweredOn:
            [self addLog:@"设备开启"];
            break;
            
        default:
            [self addLog:@"State 未知"];
            break;
    }
}

//这个方法是一旦扫描到外设就会调用的方法，注意此时并没有连接上外设，这个方法里面，你可以解析出当前扫描到的外设的广播包信息，当前RSSI等，现在很多的做法是，会根据广播包带出来的设备名，初步判断是不是自己公司的设备，才去连接这个设备，就是在这里面进行判断的
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    NSLog(@"advertisementData = %@",advertisementData);
    
    [self addLog:@"------------发现外围设备---------------"];
    [self addLog:peripheral.name];
//    [self addLog:[peripheral.RSSI stringValue]];
    [self addLog:[peripheral.identifier UUIDString]];
    
    [self.perArr addObject:peripheral];//将外围设备加入数组
    NSLog(@"%@",peripheral);
    
    [self.tableViewPer reloadData];
}




//已经连接到外围设备
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    [self addLog:@"-------------didConnectPeripheral-----------------"];
    [self addLog:peripheral.name];
    [self.tableViewPer reloadData];
    [self.perConnectedArr addObject:peripheral];
    
    peripheral.delegate = self;//设置代理
    [peripheral discoverServices:nil];//连上外围设备，然后主动发现服务
}


//连接外围设备失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    [self addLog:@"-------------didFailToConnectPeripheral-----------------"];
    [self addLog:peripheral.name];
}


//已断开外围设备连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    [self addLog:@"-------------didDisconnectPeripheral-----------------"];
    [self addLog:peripheral.name];
    [self.tableViewPer reloadData];
}



//得到可以回复设备的Array
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
    [self addLog:@"-------------didRetrievePeripherals-----------------"];
    for (CBPeripheral * peripheral in peripherals) {
        [self addLog:[NSString stringWithFormat:@"%@ name:%@",peripheral,peripheral.name]];
    }
    
}

//得到已经连上的可以回复的设备Array，这个方法当connectPeripheral:options 连接成功后被唤醒
- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
    [self addLog:@"-------------didRetrieveConnectedPeripherals-----------------"];
    for (CBPeripheral * peripheral in peripherals) {
        [self addLog:[NSString stringWithFormat:@"%@ name:%@",peripheral,peripheral.name]];
    }
}


#pragma mark CBPeripheralDelegate
//这个函数一看就知道了，当外设更新了RSSI的时候被调用，当然，外设不会无故给你老是发RSSI，听硬件那边工程师说，蓝牙协议栈里面的心跳包是可以把RSSI带过来的，但是不知道什么情况，被封杀了，你的要主动调用 [peripheral readRSSI];方法，人家外设才给你回RSSI，不过这个方法现在被弃用了。用下面的方法来接收
//已经弃用
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error
{
    [self addLog:@"-------------peripheralDidUpdateRSSI-----------------"];
    [self addLog:peripheral.name];
}


//同上，这个就是你主动调用了 [peripheral readRSSI];方法回调的RSSI，你可以根据这个RSSI估算一下距离什么的
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error NS_AVAILABLE(NA, 8_0);
{
    NSLog(@" peripheral Current RSSI:%@",RSSI);
}


//到这里，说明你上面调用的  [m_peripheral discoverServices:nil]; 方法起效果了，我们接着来找找特征值UUID
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    
    [self addLog:@"-------------didDiscoverServices-----------------"];
    [self addLog:peripheral.name];
    
    for (CBService* service in peripheral.services){
        [self addLogWithService:service];
        //查询服务所带的特征值
        [peripheral discoverCharacteristics:nil forService:service];
        //查询服务中的服务
//        [peripheral discoverIncludedServices:nil forService:service];
    }
}



//发现了（指定）的特征值了，如果你想要有所动作，你可以直接在这里做，比如有些属性为 notify 的 Characteristics ,你想要监听他们的值，可以这样写 setNotifyValue:YES forCharacteristic
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    [self addLog:@"-------------didDiscoverCharacteristicsForService-----------------"];
    [self addLog:peripheral.name];
    [self addLog:[NSString stringWithFormat:@"%@",service]];
    for (CBCharacteristic * characteristic in service.characteristics) {
        
        [self addLogWithCharacteristic:characteristic];
        //为特征添加通知
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    }
}


//这个可是重点了，你收的一切数据，基本都从这里得到,你只要判断一下 [characteristic.UUID UUIDString] 符合你们定义的哪个，然后进行处理就行，值为：characteristic.value 一切数据都是这个，至于怎么解析，得看你们自己的了
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    [self addLog:@"-------------didUpdateValueForCharacteristic-----------------"];
    [self addLog:peripheral.name];
    [self addLog:[NSString stringWithFormat:@"%@ value:%@",characteristic,characteristic.value]];

    NSData *data=characteristic.value;
    Byte *byte=(Byte *)[data bytes];
    for (int i=0; i<[data length]; i++) {
        printf("byte=%i ",byte[i]);
    }
    printf("\n");
}


//这个方法比较好，这个是你发数据到外设的某一个特征值上面，并且响应的类型是 CBCharacteristicWriteWithResponse ，上面的官方文档也有，如果确定发送到外设了，就会给你一个回应，当然，这个也是要看外设那边的特征值UUID的属性是怎么设置的,看官方文档，人家已经说了，条件是，特征值UUID的属性：CBCharacteristicWriteWithResponse
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    [self addLog:@"-------------didWriteValueForCharacteristic-----------------"];
    [self addLog:peripheral.name];
    if ([[[UIDevice currentDevice] systemVersion] floatValue]>=7.0)
    {
        [self addLog:[NSString stringWithFormat:@"%@ value:%@",characteristic,characteristic.value]];//ios7时，这里的value并不是写进去的值
    }else{
        [self addLog:[NSString stringWithFormat:@"%@ value:%@",characteristic,characteristic.value]];
    }
}

//这个方法被调用是因为你主动调用方法： setNotifyValue:forCharacteristic 给你的反馈
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    [self addLog:@"-------------didUpdateNotificationStateForCharacteristic-----------------"];
    [self addLog:peripheral.name];
    [self addLog:[NSString stringWithFormat:@"%@",characteristic]];
}


#pragma mark 蓝牙 不用
/*
//根据蓝牙设备的信息同步app状态
- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)dict
{
    [self addLog:@"-------------重置状态willRestoreState-----------------"];
    [self addLog:[NSString stringWithFormat:@"%@",dict]];
}


 
 //发现特征的描述
 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
 {
 [self addLog:@"-------------didDiscoverDescriptorsForCharacteristic-----------------"];
 [self addLog:peripheral.name];
 [self addLog:[NSString stringWithFormat:@"%@",characteristic]];
 
 }
 

//更新描述信息
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error
{
    [self addLog:@"-------------didUpdateValueForDescriptor-----------------"];
    [self addLog:peripheral.name];
    [self addLog:[NSString stringWithFormat:@"%@",descriptor]];
}


//已经写入描述信息
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error
{
    [self addLog:@"-------------didWriteValueForDescriptor-----------------"];
    [self addLog:peripheral.name];
    [self addLog:[NSString stringWithFormat:@"%@",descriptor]];
}
 
 
 
 //这个函数一般不会被调用，他被调用是因为 peripheral.name 被修改了，才会被调用
 - (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0)
 {
     [self addLog:@"-------------peripheralDidUpdateName-----------------"];
     [self addLog:peripheral.name];
 }
 
 
//这个函数一般也不会被调用，它是在你已经读取过一次外设的 services 之后，没有断开，这个时候外设突然来个我的某个服务不让用了，这个时候才会被调用，你得要再一次读取外设的 services 即可
- (void)peripheralDidInvalidateServices:(CBPeripheral *)peripheral NS_DEPRECATED(NA, NA, 6_0, 7_0)
{
    [self addLog:@"-------------peripheralDidInvalidateServices-----------------"];
    [self addLog:peripheral.name];

}


//这个函数一般也不会被调用，它是在你已经读取过一次外设的 services 之后，没有断开，这个时候外设突然来个我的某个服务不让用了，这个时候才会被调用，你得要再一次读取外设的 services 即可
- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray *)invalidatedServices NS_AVAILABLE(NA, 7_0)
{
    [self addLog:@"-------------didModifyServices-----------------"];
    [self addLog:peripheral.name];
}


//发现服务中的服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(NSError *)error
{
    [self addLog:@"-------------didDiscoverIncludedServicesForService-----------------"];
    [self addLog:peripheral.name];
    [self addLogWithService: service];
    for (CBService * server in service.includedServices) {
        [self addLogWithService: server];
        }
}
 
*/


@end
     

